//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.Collections.Generic;
using System.Text;
using ER = Microsoft.Research.DataLayer;

namespace Microsoft.Research.DataLayer
{
    #region Boolean Field
    /// <summary>
    /// Represents a boolean field in the data layer
    /// </summary>
    [Serializable]
    public class BooleanField : BaseField
    {
        /// <summary>
        /// Possible conditions of a boolean field
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// Boolean is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Boolean is not equal to value
            /// </summary>
            NotEquals,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected BooleanField(string myName)
            : base(myName)
        {
        }

        /// <summary>
        /// Create a boolean search clause
        /// </summary>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <param name="myName"></param>
        /// <returns></returns>
        /// <remarks>Condition here means BooleanField.Condition</remarks>
        protected static ISearchClause CreateSearchClause(string myName, Condition cond, bool value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region String Field
    /// <summary>
    /// Represents a string field
    /// </summary>
    [Serializable]
    public class StringField : BaseField
    {
        /// <summary>
        /// Possible conditions of a string field
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// String is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// String is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// String contains value
            /// </summary>
            Contains,

            /// <summary>
            /// String does not contain value
            /// </summary>
            NotContains,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected StringField(string myName)
            : base(myName)
        {
        }

        /// <summary>
        /// Create a string search clause
        /// </summary>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <param name="myName"></param>
        /// <returns></returns>
        /// <remarks>Condition here means StringField.Condition</remarks>
        protected static ISearchClause CreateSearchClause(string myName, Condition cond, string value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region Integer Field
    /// <summary>
    /// Represents an integer field
    /// </summary>
    [Serializable]
    public class IntegerField : BaseField
    {
        /// <summary>
        /// Possible conditions for an integer comparison
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// Integer is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Integer is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// Integer is greater than value
            /// </summary>
            GreaterThan,

            /// <summary>
            /// Integer is greater than or equal value
            /// </summary>
            GreaterThanOrEqual,

            /// <summary>
            /// Integer is less than value
            /// </summary>
            LessThan,

            /// <summary>
            /// Integer is less than or equal value
            /// </summary>
            LessThanOrEqual,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected IntegerField(string myName)
            : base(myName)
        {
        }

        /// <summary>
        /// Creates an integer search clause
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, int value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region Date/Time Field
    /// <summary>
    /// Represents a date/time field
    /// </summary>
    [Serializable]
    public class DateTimeField : BaseField
    {
        /// <summary>
        /// Possible comparisons with date/time value
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// Date/time is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Date/time is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// Date/time is less than value
            /// </summary>
            Before,

            /// <summary>
            /// Date/time is less than or equal value
            /// </summary>
            BeforeOrEqual,

            /// <summary>
            /// Date/time is greater than value
            /// </summary>
            After,

            /// <summary>
            /// Date/time is greater than or equal value
            /// </summary>
            AfterOrEqual,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected DateTimeField(string myName)
            : base(myName)
        {
        }


        /// <summary>
        /// Creates a date/time search clause
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, DateTime value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region Object Field
    /// <summary>
    /// Defines the basics for Object compile time search
    /// </summary>
    [Serializable]
    public abstract class ObjectFieldBase : BaseField
    {
        /// <summary>
        /// Possible comparisons with object value
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// Object is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Object is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// Object is null
            /// </summary>
            IsNull,

            /// <summary>
            /// Object is not null
            /// </summary>
            IsNotNull,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected ObjectFieldBase(string myName)
            : base(myName)
        {
        }
    }

    /// <summary>
    /// Represents a strong typed field object
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class ObjectField<T> : ObjectFieldBase
        where T : IObject
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected ObjectField(string myName)
            : base(myName)
        {
        }


        /// <summary>
        /// Creates an object search clause
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, T value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region Relation Field
    /// <summary>
    /// Defines the basics for Relation compile time search
    /// </summary>
    [Serializable]
    public abstract class RelationFieldBase : BaseField
    {
        /// <summary>
        /// Possible comparisons with Relation value
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// Relation is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Relation is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// Relation is null
            /// </summary>
            IsNull,

            /// <summary>
            /// Relation is not null
            /// </summary>
            IsNotNull,
        }

        /// <summary>
        /// Determines the type of relationship
        /// </summary>
        public enum RelationshipType
        {
            /// <summary>
            /// Simple relation
            /// </summary>
            Simple,

            /// <summary>
            /// Self-relation (parent side)
            /// </summary>
            Parent,

            /// <summary>
            /// Self-relation (child side)
            /// </summary>
            Child,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName">Field name</param>
        /// <param name="type">Type of relationship</param>
        protected RelationFieldBase(string myName, RelationshipType type)
            : base(myName)
        {
            Relationship = type;
        }
        
        /// <summary>
        /// Relationship type
        /// </summary>
        public RelationshipType Relationship { get; set; }
    }

    /// <summary>
    /// Represents a strong typed field Relation
    /// </summary>
    [Serializable]
    public abstract class RelationObjectFieldBase : RelationFieldBase        
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="tableName"></param>
        /// <param name="relType"></param>
        protected RelationObjectFieldBase(string myName, string tableName, RelationshipType relType)
            : base(myName, relType)
        {
            TableName = tableName;            
        }


        /// <summary>
        /// Object name of the current object
        /// </summary>
        public string TableName { get; set; }
        
    }
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public abstract class RelationSimpleFieldBase : RelationFieldBase        
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="relType"></param>
        protected RelationSimpleFieldBase(string myName, RelationshipType relType)
            : base(myName, relType)
        {
        }
        
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class RelationObjectField<T> : RelationObjectFieldBase
    where T : IObject
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="objectName"></param>
        /// <param name="relType"></param>
        protected RelationObjectField(string myName, string objectName, RelationshipType relType)
            : base(myName, objectName, relType)
        {
        }

        /// <summary>
        /// Creates a search clause for a relationship object
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, T value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }


    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public  class RelationSimpleField<T> : RelationSimpleFieldBase
        where T : IObject
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="relType"></param>
        protected RelationSimpleField(string myName, RelationshipType relType)
            : base(myName, relType)
        {
        }

        /// <summary>
        /// Creates a search clause for a relationship field
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, T value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }

    #endregion

    #region Enum Field
    /// <summary>
    /// Defines the basics for Enum compile time search
    /// </summary>
    [Serializable]
    public abstract class EnumFieldBase : BaseField
    {
        /// <summary>
        /// Possible comparisons with enum value
        /// </summary>
        [Serializable]
        public enum Condition
        {
            /// <summary>
            /// Enum is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// Enum is not equal to value
            /// </summary>
            NotEquals,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected EnumFieldBase(string myName)
            : base(myName)
        {
        }
    }

    /// <summary>
    /// Represents an enumfield
    /// </summary>
    [Serializable]
    public class EnumField<T> : EnumFieldBase
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected EnumField(string myName)
            : base(myName)
        {
        }

        /// <summary>
        /// Creates an enum search clause
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, T value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion

    #region URI Field
    /// <summary>
    /// Represents an URI field
    /// </summary>
    [Serializable]
    public class URIField : BaseField
    {
        /// <summary>
        /// Possible conditions for an URI comparison
        /// </summary>
        public enum Condition
        {
            /// <summary>
            /// URI is equal to value
            /// </summary>
            Equals,

            /// <summary>
            /// URI is not equal to value
            /// </summary>
            NotEquals,

            /// <summary>
            /// URI contains value
            /// </summary>
            Contains,

            /// <summary>
            /// URI does not contain value
            /// </summary>
            NotContains,

            /// <summary>
            /// URI uses specific protocol
            /// </summary>
            UseProtocol,

            /// <summary>
            /// URI does not use specific protocol
            /// </summary>
            NotUseProtocol,
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="myName"></param>
        protected URIField(string myName)
            : base(myName)
        {
        }

        /// <summary>
        /// Creates an URI search clause
        /// </summary>
        /// <param name="myName"></param>
        /// <param name="cond"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static ISearchClause CreateSearchClause(string myName, Condition cond, Uri value)
        {
            SearchClause newClause = new SearchClause(myName, cond, value);
            return newClause;
        }
    }
    #endregion
}
